<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
      <el-form-item label="题型" prop="questionType">
        <el-select v-model="queryParams.questionType" placeholder="请选择题目类型" clearable>
          <el-option v-for="dict in dict.type.exam_question_type" :key="dict.value" :label="dict.label"
            :value="dict.value" />
        </el-select>
      </el-form-item>
      <el-form-item label="题库" prop="outline">
        <el-input v-model="queryParams.outline" placeholder="请输入题库关键字" clearable @keyup.enter.native="handleQuery" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <!-- <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
          v-hasPermi="['exam:question:add']">新增</el-button> -->
        <el-popover placement="bottom" trigger="click">
          <el-button type="warning" size="mini" v-for="item in dict.type.exam_question_type" :key="item.key"
            @click="handleAdd(item.value)">{{
              item.label }}
          </el-button>
          <el-button slot="reference" type="primary" plain icon="el-icon-plus" size="mini"
            v-hasPermi="['exam:question:add']">新增</el-button>
        </el-popover>
      </el-col>
      <el-col :span="1.5">
        <el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
          v-hasPermi="['exam:question:edit']">修改</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
          v-hasPermi="['exam:question:remove']">删除</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
          v-hasPermi="['exam:question:export']">导出</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="info" plain icon="el-icon-upload2" size="mini" @click="handleImport"
          v-hasPermi="['exam:question:import']">导入</el-button>
      </el-col>
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
    </el-row>

    <el-table v-loading="loading" :data="questionList" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column label="题型" align="center" prop="questionType" width="100">
        <template slot-scope="scope">
          <dict-tag :options="dict.type.exam_question_type" :value="scope.row.questionType" />
        </template>
      </el-table-column>
      <el-table-column label="题库" align="center" prop="outline" width="180" show-overflow-tooltip />
      <el-table-column label="题目名称" align="left" prop="questionTitle" min-width="300" show-overflow-tooltip>
        <template slot-scope="scope">
          <span style="margin-left: 10px;">{{ scope.row.questionTitle }}</span>
        </template>
      </el-table-column>
      <el-table-column label="题目答案" align="center" prop="questionAnswer" width="100" />
      <el-table-column label="答案解析" align="center" prop="questionAnswerExplain" width="200" show-overflow-tooltip />
      <el-table-column label="分值" align="center" prop="questionScore" width="80" />
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
        <template slot-scope="scope">
          <span>{{ parseTime(scope.row.createTime) }}</span>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template slot-scope="scope">
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
            v-hasPermi="['exam:question:edit']">修改</el-button>
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
            v-hasPermi="['exam:question:remove']">删除</el-button>
        </template>
      </el-table-column>
    </el-table>

    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
      @pagination="getList" />
    <!-- 帮我新建一个el-dialog，弹窗里面的form通过参数来确定是使用singleChoice还是multipleChoice -->
    <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
      <single-choice v-if="String(form.questionType) === '1'" :questionType="String(form.questionType)" :question="form"
        @triggerSubmitForm="submitForm" />
      <multiple-choice v-if="String(form.questionType) === '2'" :questionType="String(form.questionType)"
        :question="form" @triggerSubmitForm="submitForm" />
      <true-false v-if="String(form.questionType) === '3'" :questionType="String(form.questionType)" :question="form"
        @triggerSubmitForm="submitForm" />
    </el-dialog>

    <el-dialog :title="upload.title" :visible.sync="upload.open" width="800px" append-to-body class="upload-dialog">
      <div class="upload-container">
        <!-- 上传区域 -->
        <div class="upload-area">
          <el-upload ref="upload" :multiple="true" action="#" :disabled="upload.isUploading" :auto-upload="false"
            :on-change="handleFileChange" :on-remove="handleFileRemove" :before-upload="handleBeforeUpload" drag
            :show-file-list="false" class="upload-demo">
            <i class="el-icon-upload"></i>
            <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
            <div class="el-upload__tip text-center" slot="tip">
              <span>仅允许导入xls、xlsx格式文件。</span>
            </div>
          </el-upload>
          <!-- 自定义文件列表 -->
          <div v-if="upload.files.length > 0" class="custom-file-list">
            <div v-for="(file, index) in upload.files" :key="index" class="file-item">
              <span class="file-name" :title="file.name">{{ file.name }}</span>
              <el-button type="text" class="file-remove" @click="handleFileRemove(file)" :disabled="upload.isUploading">
                <i class="el-icon-delete"></i>
              </el-button>
            </div>
          </div>
        </div>

        <!-- 文件处理状态列表 -->
        <div class="file-status-list">
          <el-table :data="upload.files" size="small" height="300" style="width: 100%" row-key="uid"
            :expand-row-keys="expandRows" @expand-change="handleExpand">
            <el-table-column type="expand">
              <template slot-scope="scope">
                <div v-if="scope.row.errors && scope.row.errors.length" class="error-details">
                  <div v-for="(error, index) in scope.row.errors" :key="index" class="error-item">
                    <i class="el-icon-warning-outline"></i>
                    {{ error }}
                  </div>
                </div>
              </template>
            </el-table-column>
            <el-table-column prop="name" label="文件名" show-overflow-tooltip></el-table-column>
            <el-table-column label="状态" width="100" align="center">
              <template slot-scope="scope">
                <el-tag v-if="scope.row.status === 'waiting'" type="info" size="mini">等待中</el-tag>
                <el-tag v-if="scope.row.status === 'processing'" type="warning" size="mini">处理中</el-tag>
                <el-tag v-if="scope.row.status === 'success'" type="success" size="mini">成功</el-tag>
                <el-tag v-if="scope.row.status === 'error'" type="danger" size="mini">失败</el-tag>
                <el-tag v-if="scope.row.status === 'warning'" type="warning" size="mini">部分成功</el-tag>
              </template>
            </el-table-column>
            <el-table-column label="结果" min-width="300" show-overflow-tooltip>
              <template slot-scope="scope">
                <span v-if="scope.row.result">{{ scope.row.result }}</span>
                <span v-if="scope.row.errors && scope.row.errors.length">
                  <el-link type="warning" @click.stop="handleExpand(scope.row)">
                    点击查看详情
                  </el-link>
                </span>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </div>

      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitFileForm" :loading="upload.isUploading">确 定</el-button>
        <el-button @click="cancel">取 消</el-button>
      </div>
    </el-dialog>

  </div>
</template>

<script>
import { getToken } from "@/utils/auth";
import { listQuestion, getQuestion, delQuestion, addQuestion, updateQuestion, importTemplate, importData } from "@/api/exam/question";

import singleChoice from "./components/single-choice.vue";
import multipleChoice from "./components/multiple-choice.vue";
import trueFalse from "./components/true-false.vue";

export default {
  name: "Question",
  dicts: ['exam_question_type', 'job_category'],
  components: { singleChoice, multipleChoice, trueFalse },
  data() {
    return {
      // 遮罩层
      loading: true,
      // 选中数组
      ids: [],
      // 非单个禁用
      single: true,
      // 非多个禁用
      multiple: true,
      // 显示搜索条件
      showSearch: true,
      // 总条数
      total: 0,
      // 题目，存储题目信息表格数据
      questionList: [],
      // 弹出层标题
      title: "",
      // 是否显示弹出层
      open: false,
      // 查询参数
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        questionType: null,
        questionTitle: null,
        jobCategory: null,
        outline: null
      },
      // 表单参数
      form: {
        resetForm: false,
        outline: null
      },
      // 表单校验
      rules: {
        questionTitle: [
          { required: true, message: "题目名称不能为空", trigger: "blur" }
        ],
        questionText: [
          { required: true, message: "题目内容,不同的json内容表示不同的选项内容不能为空", trigger: "blur" }
        ],
        questionAnswer: [
          { required: true, message: "题目答案不能为空", trigger: "blur" }
        ],
        questionAnswerExplain: [
          { required: true, message: "题目答案解析不能为空", trigger: "blur" }
        ],
        outline: [
          { required: true, message: "题库不能为空", trigger: "blur" }
        ]
      },
      upload: {
        open: false,
        title: '',
        isUploading: false,
        updateSupport: 0,
        files: [],
        expandRows: []  // 当前展开的行
      },
      expandRows: []  // 当前展开的行
    };
  },
  created() {
    this.getList();
  },
  methods: {
    /** 查询题目，存储题目信息列表 */
    getList() {
      this.loading = true;
      listQuestion(this.queryParams).then(response => {
        this.questionList = response.rows;
        this.total = response.total;
        this.loading = false;
      });
    },
    // 取消按钮
    cancel() {
      this.upload.open = false;
      this.upload.files = [];
      this.expandRows = []; // 重置展开行状态
      this.upload.expandRows = []; // 重置上传组件的展开行状态
    },
    // 表单重置
    reset() {
      this.form = {
        resetForm: false,
        outline: null
      };
      this.resetForm("form");
    },
    /** 搜索按钮操作 */
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.getList();
    },
    /** 重置按钮操作 */
    resetQuery() {
      this.resetForm("queryForm");
      this.handleQuery();
    },
    // 多选框选中数据
    handleSelectionChange(selection) {
      this.ids = selection.map(item => item.id)
      this.single = selection.length !== 1
      this.multiple = !selection.length
    },
    /** 新增按钮操作 */
    handleAdd(value) {
      this.reset();
      this.form.resetForm = true;
      this.open = true;
      this.form.questionType = value;
      this.title = "添加试题";
    },
    /** 修改按钮操作 */
    handleUpdate(row) {
      const id = row.id || this.ids
      getQuestion(id).then(response => {
        this.form = response.data;
        // 将form的questionText字符串转换为数组
        this.form.items = JSON.parse(this.form.questionText);
        // 类型转换
        if (this.form.jobCategory) {
          this.form.jobCategory = String(this.form.jobCategory);
        }
        // 多选题情况下questionAnswer是数组
        if (String(this.form.questionType) === '2') {
          this.form.correctArray = JSON.parse(this.form.questionAnswer);
        }
        this.open = true;
        this.title = "修改试题";
      });
    },
    /** 提交按钮 */
    submitForm() {
      this.open = false;
      this.getList();
    },
    /** 删除按钮操作 */
    handleDelete(row) {
      const ids = row.id || this.ids;
      this.$modal.confirm('是否确认删除题目，存储题目信息编号为"' + ids + '"的数据项？').then(function () {
        return delQuestion(ids);
      }).then(() => {
        this.getList();
        this.$modal.msgSuccess("删除成功");
      }).catch(() => { });
    },
    /** 导出按钮操作 */
    handleExport() {
      this.download('exam/question/export', {
        ...this.queryParams
      }, `question_${new Date().getTime()}.xlsx`)
    },
    /** 导入按钮操作 */
    handleImport() {
      this.upload.open = true;
      this.upload.files = [];
      this.expandRows = []; // 重置展开行状态
      this.upload.expandRows = []; // 重置上传组件的展开行状态
      this.upload.isUploading = false; // 重置上传状态
      // 重置上传组件
      if (this.$refs.upload) {
        this.$refs.upload.clearFiles();
      }
    },
    /** 下载模板操作 */
    importTemplate() {
      this.download('exam/question/importTemplate', {
      }, `question_template_${new Date().getTime()}.xlsx`)
    },
    // 文件选择处理
    handleFileChange(file, fileList) {
      // 先清除el-upload组件内部的文件列表中可能存在的重复项
      const uniqueFiles = [];
      const fileIds = new Set();

      for (const f of fileList) {
        // 使用文件名和大小作为唯一标识
        const fileId = `${f.name}-${f.size}`;
        if (!fileIds.has(fileId)) {
          fileIds.add(fileId);
          uniqueFiles.push(f);
        }
      }

      // 为每个文件添加状态信息
      this.upload.files = uniqueFiles.map(f => ({
        ...f,
        uid: f.uid || Math.random().toString(36).substr(2),  // 确保每个文件都有唯一的uid
        status: 'waiting',  // waiting, processing, success, error
        result: ''
      }));
    },
    // 文件移除处理
    handleFileRemove(file) {
      // 通过file.uid找到并删除对应的文件
      this.upload.files = this.upload.files.filter(f => f.uid !== file.uid);
    },
    // 文件上传前的检查
    handleBeforeUpload(file) {
      const isExcel = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ||
        file.type === 'application/vnd.ms-excel';
      if (!isExcel) {
        this.$message.error('只能上传 Excel 文件！');
        return false;
      }
      return true;
    },
    /** 提交上传文件 */
    async submitFileForm() {
      if (this.upload.files.length === 0) {
        this.$message.warning("请选择需要导入的文件！");
        return;
      }
      this.upload.isUploading = true;

      // 最大重试次数
      const MAX_RETRIES = 3;
      const RETRY_DELAY = 2000; // 2秒

      // 依次处理每个文件
      for (let file of this.upload.files) {
        if (file.status === 'success' || file.status === 'error') {
          continue;  // 跳过已处理的文件
        }

        // 重试计数器
        let retryCount = 0;
        let success = false;

        while (!success && retryCount < MAX_RETRIES) {
          // 更新状态为处理中
          file.status = 'processing';

          try {
            const formData = new FormData();
            formData.append('files', file.raw);

            const response = await importData(formData);
            const result = JSON.parse(response.msg);

            if (result.errors && result.errors.includes("该文件正在处理中，请稍后再试")) {
              retryCount++;
              if (retryCount < MAX_RETRIES) {
                file.status = 'waiting';
                file.result = `等待重试 (${retryCount}/${MAX_RETRIES})`;
                await new Promise(resolve => setTimeout(resolve, RETRY_DELAY));
                continue;
              } else {
                file.status = 'error';
                file.result = '重试次数已达上限';
                break;
              }
            }

            if (result.failure === 0) {
              file.status = 'success';
              file.result = `成功导入 ${result.success} 条数据`;
              success = true;
            } else {
              file.status = 'warning';
              file.result = `成功：${result.success}，失败：${result.failure}`;
              file.errors = result.errors;
              success = true;
            }

          } catch (error) {
            retryCount++;
            if (retryCount < MAX_RETRIES) {
              file.status = 'waiting';
              file.result = `处理失败，等待重试 (${retryCount}/${MAX_RETRIES})`;
              await new Promise(resolve => setTimeout(resolve, RETRY_DELAY));
              continue;
            } else {
              file.status = 'error';
              file.result = '导入失败：' + (error.response?.msg || error.message || '未知错误');
              break;
            }
          }
        }

        // 每个文件处理完后等待一段时间
        await new Promise(resolve => setTimeout(resolve, 1000));
      }

      // 检查所有文件的处理结果
      const successCount = this.upload.files.filter(f => f.status === 'success' || f.status === 'warning').length;
      const totalCount = this.upload.files.length;

      if (successCount === totalCount) {
        this.$message({
          message: '文件处理完成',
          type: 'success'
        });
        // 仅刷新列表数据
        this.getList();
      } else {
        this.$message({
          message: '部分文件处理失败，请查看详情',
          type: 'warning'
        });
      }

      this.upload.isUploading = false;
    },
    // 处理展开/折叠
    handleExpand(row) {
      // 切换展开状态
      if (this.expandRows.includes(row.uid)) {
        this.expandRows = this.expandRows.filter(uid => uid !== row.uid);
      } else {
        this.expandRows = [row.uid];  // 只展开当前行
      }
    }
  }
};
</script>

<style lang="scss" scoped>
.upload-dialog {
  :deep(.el-dialog__body) {
    padding: 20px;
  }
}

.upload-container {
  .upload-area {
    margin-bottom: 20px;

    .el-upload-dragger {
      width: 100%;
    }

    .custom-file-list {
      margin-top: 10px;
      max-height: 120px;
      overflow-y: auto;
      border: 1px solid #EBEEF5;
      border-radius: 4px;
      padding: 5px;

      .file-item {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 5px 10px;
        border-bottom: 1px solid #F2F6FC;

        &:last-child {
          border-bottom: none;
        }

        .file-name {
          flex: 1;
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
          margin-right: 10px;
          color: #606266;
        }

        .file-remove {
          padding: 0;
          color: #F56C6C;

          &:hover {
            color: #f78989;
          }

          &[disabled] {
            color: #C0C4CC;
            cursor: not-allowed;
          }
        }
      }
    }
  }
}

.file-status-list {
  border: 1px solid #EBEEF5;
  border-radius: 4px;
  padding: 10px;

  .el-table {
    :deep(.el-table__body-wrapper) {
      overflow-y: auto;
    }
  }
}

.error-details {
  padding: 10px 20px;
  background-color: #FFF9F9;

  .error-item {
    color: #F56C6C;
    line-height: 24px;
    margin: 4px 0;

    .el-icon-warning-outline {
      margin-right: 8px;
    }
  }
}
</style>
